package org.NooLab.glue.msgframe;

import org.NooLab.compare.utilities.math.DistanceControlProperties;
import org.NooLab.glue.subscription.Future;
import org.NooLab.glue.subscription.FutureProperties;
import org.NooLab.glue.subscription.context.Comparison;
import org.NooLab.utilities.logging.PrintLog;
import org.NooLab.utilities.objects.StringedObjects;
import org.NooLab.utilities.xml.XMessageAbs;

import com.jamesmurty.utils.XMLBuilder;



public class FXMessage extends XMessageAbs{

	
	DistanceControlProperties distanceCtrl;
	
	public FXMessage( PrintLog outprn ){
		super();
			
		out = outprn;
	}
	
	
	public void setDistanceControlProperties( DistanceControlProperties distancectrl ) {
		distanceCtrl = new DistanceControlProperties(distancectrl); 
	}
	
	/**
	 * 
	 * this creates a xml of a subscription that is defined in plain, simple style, as item set
	 *  
	 * @param future
	 * @param basics
	 * @param action
	 * @return
	 */
	public String createXmlFromFutureSimple( Future future , BasicMessageParams basics,  String action){
		/*
			<messageboard name="spela" role="SOURCE">
				<subscription action="define">
				<instance id="2528" name="" />
				
				<properties id="85313bb1-17c6-47ca-bf14-7ced92d03d46" type="1">   type=1 == plain, 2==context
				
					<property id="0" label="keywords">
						<items type="incl" values="a;b;c;d"/>
						<items type="excl" values="x"/>
					</property>
					
					<property id="1" label="match" >
						<items type="threshold" value="0.71">
					</property>
				
					</properties>
				</subscription>
		</messageboard>
	*/		
		String xmlstr = "", pxmlstr="", vstr, str="", strx="";
		 
		String typeLabel="";
		 
		
		FutureProperties prop ;
		XMLBuilder builder, pbuilds;
		
		
		try {
	
			
			builder = getXmlBuilder( "messageboard" ).a( "name", "spela").a("role", basics.roleOfSender ); 
			
			builder.e("subscription").a("action", action)
					 .e("instance").a("id", ""+basics.instanceID).a("name", basics.instanceName).up()
					 .t("$properties$").up() ;
			
			if (future.getProperties().size()>0){
				prop = future.getProperties().get(0) ;
				typeLabel = ""+prop.getType();
				
				if (prop.getType()>2){
					return "";
				}
				
				Comparison comp = new Comparison(out);
				
				
				String[] xitems = comp.removeIntersectionOfSetsFrom( 1, prop.getExclvalues(), prop.getValues());
				
				str = strgutil.arr2text( xitems, "", ";") ; 
				// using string as input format enforces a new object !
				prop.setExclvalues( str );
			}
			
			pbuilds = getXmlBuilder("properties").a("id", basics.privateTransactionIdentifier).a("type", ""+typeLabel);
				
			int n = future.getProperties().size() ;
			 
			
			
			pbuilds.e("distanceControl")
					.e("missingvalue").a("method", ""+distanceCtrl.getDistanceMethod())
					 			      .a("handling", ""+distanceCtrl.getMissingValueHandling()).up() 
		    	    .e("surrogatdistance").a( "value",""+distanceCtrl.getSurrogateDistance()).up() 
		    	    .e("itemsetcontrast").a("sigma", ""+distanceCtrl.getItemSetContrastsigma())
		    	                         .a("alpha", ""+distanceCtrl.getItemSetContrastalpha())
		    							 .a("beta", ""+distanceCtrl.getItemSetContrastbeta())
		    							 .a("method", ""+distanceCtrl.getSetSimMethod() ).up();
		    
			pbuilds.up(); // closing e("distanceControl")
			 
			
			for (int i=0;i<n;i++){
			
				
				prop = future.getProperties().get(i) ;
				  
				
				str = strgutil.arr2text( prop.getValues(), "", ";");

				if ( prop.getExclvalues()!=null){
					strx = strgutil.arr2text( prop.getExclvalues(), "", ";");
				}
				
				vstr = ""+prop.getMinimalMatch();
				
				pbuilds.e( "property" ).a("id", "1")
									   .a("label",prop.getKey() )
									   .a("name", prop.getName() )	 
	                        .e("items").a("type", "incl").a("values", ""+str).up()
	                        .e("items").a("type", "excl").a("values", ""+strx).up()
					    .up() 
	
					    .e("property").a("id", "2").a("label", "threshold" )
			      			.e("items").a("type", "match") .a("value", vstr).up()
			      		.up()
				;
				
			} // i->
					
			 
			pxmlstr = getXmlStr(pbuilds, false);
			pxmlstr =  pxmlstr.replace( "<prop","   <prop");
			pxmlstr =  pxmlstr.replace( "</prop","   </prop");
			xmlstr = getXmlStr(builder, true);
			
			xmlstr =  xmlstr.replace( "$properties$", "\r\n"+pxmlstr) ;
			// "</subscription>"
			
	
		} catch (Exception e) {
			e.printStackTrace();
		}
	
		return xmlstr;
	}


	/* note that xmlbuilder does not allow to interrupt a building-chain for conditional proceeding,
	 * interrupted tags will be closed too early !!!
	 * 
	 * though it is not really elegant and some things repeat we nevertheless have to separate 
	 * the types into different & dedicated methods  
	 */
	public String createXmlFromFutureFeatureVector( Future future , BasicMessageParams basics,  String action){
		
		String xmlstr = "", pxmlstr="",  vmastr="", vsistr="",str="", strx="",strn="";
		int alignmentBypassValue=0; 
		String typeLabel="";
		boolean isFeatureVector ;
		
		FutureProperties prop ;
		XMLBuilder builder, pbuilds;
		// DistanceControlProperties distanceCtrl ;
		
		try {
 
			
			builder = getXmlBuilder( "messageboard" ).a( "name", "spela").a("role", basics.roleOfSender ); 
			
			builder.e("subscription").a("action", action)
					 .e("instance").a("id", ""+basics.instanceID).a("name", basics.instanceName).up()
					 .t("$properties$").up() ;
			
			if (future.getProperties().size()>0){
				prop = future.getProperties().get(0) ;
				typeLabel = ""+prop.getType();
				
				if (prop.getType()!= FutureProperties._VECTOR){
					return "";
				}
				
				Comparison comp = new Comparison(out);
				
				
				String[] xitems = comp.removeIntersectionOfSetsFrom( 1, prop.getExclvalues(), prop.getValues());
				if (xitems==null){ xitems = new String[0];}
				
				str = strgutil.arr2text( xitems, "", ";") ; 
				// using string as input format enforces a new object !
				prop.setExclvalues( str );
			}
			
			pbuilds = getXmlBuilder("properties").a("id", basics.privateTransactionIdentifier)
											     .a("type", ""+typeLabel);
				
			int n = future.getProperties().size() ;
			 
			if (distanceCtrl.getBypassVectorAlignCheck()){
				alignmentBypassValue = 1;
			}
			
			pbuilds.e("distanceControl")
					.e("missingvalue").a("method", ""+distanceCtrl.getDistanceMethod())
					 			      .a("handling", ""+distanceCtrl.getMissingValueHandling()).up() 
		    	    .e("surrogatdistance").a( "value",""+distanceCtrl.getSurrogateDistance()).up() 
		    	    .e("alignment").a("bypassmode", ""+alignmentBypassValue).up()
		    	    .e("itemsetcontrast").a("sigma", ""+distanceCtrl.getMvItemSetContrastsigma())
		    	    					 .a("alpha", ""+distanceCtrl.getItemSetContrastalpha())
		    							 .a("beta", ""+distanceCtrl.getItemSetContrastbeta())
		    							 .a("method", ""+distanceCtrl.getSetSimMethod() ) .up();
		    
			pbuilds.up(); // closing e("distanceControl")
			 
			
			for (int i=0;i<n;i++){
			
				
				prop = future.getProperties().get(i) ;
				
				isFeatureVector = (prop.getType() == FutureProperties._VECTOR) ;
				if (isFeatureVector==false){
					continue;
				}
				
				str = strgutil.arr2text( prop.getValues(), "", ";");
				strn = strgutil.arr2text(prop.getDataValues(), 8, true, ";");
				
				if ( prop.getExclvalues()!=null){
					strx = strgutil.arr2text( prop.getExclvalues(), "", ";");
				}
				
				vmastr = ""+prop.getMinimalMatch();
				vsistr = ""+prop.getMinimalProfileSimilarity();
				
				pbuilds.e( "property" ).a("id", "1")
									   .a("label",prop.getKey() )
                					   .a("name", prop.getName() )	 
					   	    .e("items").a("type", "features").a("values", ""+str).up()
					   	    .e("items").a("type","numdata").a("values", ""+strn).up()
					   	    .e("items").a("type", "excl").a("values", ""+strx).up()
						.up()
				
						.e("property").a("id", "2").a("label", "threshold" )
			      			.e("items").a("type", "match") .a("value", vmastr).up()
			      			.e("items").a("type", "similarity") .a("value", vsistr).up()
			      		.up()
				;
				
			} // i->
					
			 
			pxmlstr = getXmlStr(pbuilds, false);
			pxmlstr =  pxmlstr.replace( "<prop","   <prop");
			pxmlstr =  pxmlstr.replace( "</prop","   </prop");
			xmlstr = getXmlStr(builder, true);
			
			xmlstr =  xmlstr.replace( "$properties$", "\r\n"+pxmlstr) ;
			// "</subscription>"
			

		} catch (Exception e) {
			e.printStackTrace();
		}

		return xmlstr;
	}

		
	/**
	 * 
	 * this creates an xml representation of an extended context definition<br/>
	 * 
	 * usually, the context definition is included in encoded form (encodeObj=1)
	 * 
	 * @param future
	 * @param encodeObj 
	 * @param basics
	 * @param action
	 * @return
	 */
	public String createXmlFromFutureCtxt( Future future, int encodeObj, BasicMessageParams basics,  String action){ 
	
		String xmlstr = "", objstr, pxmlstr="" ;
		 
		String typeLabel="";
		
		FutureProperties prop ;
		XMLBuilder builder, pbuilds;
		StringedObjects strgObj = new StringedObjects();
		
		try {
	
			
			builder = getXmlBuilder( "messageboard" ).a( "name", "spela").a("role", basics.roleOfSender ); 
			
			builder.e("subscription").a("action", action)
					 .e("instance").a("id", ""+basics.instanceID).a("name", basics.instanceName).up()
					 .t("$properties$").up() ;
			
			if (future.getProperties().size()>0){
				prop = future.getProperties().get(0) ;
				typeLabel = ""+prop.getType();
				
				if (prop.getType()!= FutureProperties._CONTEXT){
					return "";
				}
			} else{
				return "";
			}
			
			objstr = strgObj.encode( future.getProperties().get(0).getContext() );
			 
			pbuilds = getXmlBuilder("properties").a("id", basics.privateTransactionIdentifier).a("type", ""+typeLabel);
			
			
			pbuilds.e( "context" ).t("$context$").up();
			
			
			pxmlstr = getXmlStr(pbuilds, false);
			pxmlstr = pxmlstr.replace("$context$", objstr);
			
			xmlstr = getXmlStr(builder, true);
			xmlstr =  xmlstr.replace( "$properties$", "\r\n"+pxmlstr) ;
			
		}catch(Exception e){
		}
		
		return xmlstr;
	}


	public String createXmlFromFutureFullText( Future future , BasicMessageParams basics,  String action){
		String xmlstr = "", pxmlstr="", vstr, str="", strx="";
		 
		String typeLabel="";
		
		FutureProperties prop ;
		XMLBuilder builder, pbuilds;
		
		
		try {
	
			
			builder = getXmlBuilder( "messageboard" ).a( "name", "spela").a("role", basics.roleOfSender ); 
			
			builder.e("subscription").a("action", action)
					 .e("instance").a("id", ""+basics.instanceID).a("name", basics.instanceName).up()
					 .t("$properties$").up() ;
			
			if (future.getProperties().size()>0){
				prop = future.getProperties().get(0) ;
				typeLabel = ""+prop.getType();
				
				if (prop.getType()!= FutureProperties._FREETEXT){
					return "";
				}
				
				Comparison comp = new Comparison(out);
				
				
				String[] xitems = comp.removeIntersectionOfSetsFrom( 1, prop.getExclvalues(), prop.getValues());
				
				str = strgutil.arr2text( xitems, "", ";") ; 
				// using string as input format enforces a new object !
				prop.setExclvalues( str );
			}
			
			pbuilds = getXmlBuilder("properties").a("id", basics.privateTransactionIdentifier).a("type", ""+typeLabel);
				
			int n = future.getProperties().size() ;
			 
			
			
			pbuilds.e("distanceControl")
					.e("missingvalue").a("method", ""+distanceCtrl.getDistanceMethod())
					 			      .a("handling", ""+distanceCtrl.getMissingValueHandling()).up() 
		    	    .e("surrogatdistance").a( "value",""+distanceCtrl.getSurrogateDistance()).up() 
		    	    .e("itemsetcontrast").a("alpha", ""+distanceCtrl.getItemSetContrastalpha())
		    							 .a("beta", ""+distanceCtrl.getItemSetContrastbeta()).up() ;
		    
			pbuilds.up(); // closing e("distanceControl")
			 
			
			for (int i=0;i<n;i++){
			
				
				prop = future.getProperties().get(i) ;
				 
				
				str = strgutil.arr2text( prop.getValues(), "", ";");
				 
				if ( prop.getExclvalues()!=null){
					strx = strgutil.arr2text( prop.getExclvalues(), "", ";");
				}
				
				vstr = ""+prop.getMinimalMatch();
				
				pbuilds.e( "property" ).a("id", "1")
									   .a("label",prop.getKey() )
									   .a("name", prop.getName() )	 
									   
	                        .e("items").a("type", "excl").a("values", ""+strx).up()
	                        .t( prop.getFullText() ).up() 
					    .up() 
					    .e("property").a("id", "2").a("label", "threshold" )
			      			.e("items").a("type", "match") .a("value", vstr).up()
			      		.up()
				;
				
			} // i->
					
			 
			pxmlstr = getXmlStr(pbuilds, false);
			pxmlstr =  pxmlstr.replace( "<prop","   <prop");
			pxmlstr =  pxmlstr.replace( "</prop","   </prop");
			xmlstr = getXmlStr(builder, true);
			
			xmlstr =  xmlstr.replace( "$properties$", "\r\n"+pxmlstr) ;
			// "</subscription>"
			
	
		} catch (Exception e) {
			e.printStackTrace();
		}
	
		return xmlstr;
	}
	
	
	public String createXmlForUnpublishingFuture(Future future , BasicMessageParams basics,  String action){
		
		String xmlstr="";
		XMLBuilder builder;
		
		
		try{
			
			builder = getXmlBuilder( "messageboard" ).a( "name", "spela").a("role", basics.roleOfSender ); 
			
			builder.e("subscription").a("action", action).a("name", basics.privateTransactionIdentifier)
					 .e("instance").a("id", ""+basics.instanceID).up()
					 .up() ;
			
			xmlstr = getXmlStr(builder, true);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return xmlstr;
	}
	
	
	
	
	
}
